using NHibernate.Validator.Constraints;
using SharpArch.Core.PersistenceSupport;
using SharpArch.Core.DomainModel;
using System;
using SharpArch.Core;
using System.Collections.Generic;

namespace GoldenBicycleCompany.Core
{
    public class Rental : Entity
    {
        private IList<PentaltyFee> _pentaltyFees;
        private IList<Bicycle> _bicycles;

        private void Initialize() {
            _pentaltyFees = new List<PentaltyFee>();
        }

        public Rental() {
            Initialize();
        }

        public Rental(Customer customer, DateTime pickupDateTime, DateTime dropOffDatetime) : this() {
            this.IsLate = false;
            this.PickUpDateTime = pickupDateTime;
            this.RequestedDropOffDateTime = dropOffDatetime;
            this.Customer = customer;
        }
        
        [NotNull]
        public virtual Customer Customer { get; set; }

        [NotNull]
        public virtual IEnumerable<Bicycle> Bicycles {
            get {
                return _bicycles;
            }

            set {
                _bicycles = value as IList<Bicycle>;
            }
        }

        [NotNull]
        public virtual IEnumerable<PentaltyFee> PentaltyFees {
            get {
                return _pentaltyFees;
            }

            set {
                _pentaltyFees = value as IList<PentaltyFee>;
            }
        }

        public virtual DateTime ActualDropOffDateTime { get; set; }

        public virtual DateTime PickUpDateTime { get; set; }

        public virtual DateTime RequestedDropOffDateTime { get; set; }

        public virtual bool IsLate { get; set; }

        public virtual bool NotifiedWillBeLate { get; set; }

        public virtual void AddCustomer(Customer customer) {
            Check.Require(!ReferenceEquals(null, customer), "customer cannot be null");

            this.Customer = customer;
        }

        public virtual void ChangeCustomer(Customer customer) {
            Check.Require(!ReferenceEquals(null, customer), "customer cannot be null");

            this.Customer = customer;
        }

        public virtual void AddBicycles(IList<Bicycle> bicycles) {
            _bicycles.Clear();

            foreach (Bicycle bicycle in bicycles) {
                this.AddBicycle(bicycle);
            }
        }

        public virtual void AddBicycle(Bicycle bicycle) {
            Check.Require(!ReferenceEquals(null, bicycle), "bicycle cannot be null");

            if (!_bicycles.Contains(bicycle)) {
                _bicycles.Add(bicycle);
            }
        }

        public virtual void RemoveBicycle(Bicycle bicycle) {
            Check.Require(!ReferenceEquals(null, bicycle), "bicycle cannot be null");

            if (_bicycles.Contains(bicycle)) {
                _bicycles.Remove(bicycle);
            }
        }

        public virtual void AddPentaltyFee(PentaltyFee pentaltyFee) {
            Check.Require(!ReferenceEquals(null, pentaltyFee), "pentaltyFee cannot be null");

            _pentaltyFees.Add(pentaltyFee);
        }

        public virtual void RemovePentaltyFee(PentaltyFee pentaltyFee) {
            Check.Require(!ReferenceEquals(null, pentaltyFee), "bicycle cannot be null");

            _pentaltyFees.Remove(pentaltyFee);
        }

        public virtual void ChangeLateness(bool isLate) {
            this.IsLate = isLate;
        }

        public virtual void ChangeActualDropOffDateTime(DateTime actualDropOffDateTime) {
            this.ActualDropOffDateTime = actualDropOffDateTime;
        }

        public virtual void ChangePickUpDateTime(DateTime pickupDateTime) {
            this.PickUpDateTime = pickupDateTime;
        }

        public virtual void ChangeRequestedDropOffDateTime(DateTime requestedDropOffDateTime) {
            this.RequestedDropOffDateTime = requestedDropOffDateTime;
        }

        public virtual void ChangeCustomerNotifiedWillBeLate(bool customerNotifiedWillBeLate) {
            this.NotifiedWillBeLate = customerNotifiedWillBeLate;
        }
    }
}
